package framework.common.zanetwork.core;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParseException;

import net.zhuike.novel.app.ZhuiKeApplication;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import framework.common.zanetwork.ResponseResult;
import framework.utils.NetWorkUtil;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class HttpHelper {

    public static final MediaType MEDIA_TYPE_JSON
            = MediaType.parse("text/html; charset=utf-8");
    /**
     * 采用单例模式使用OkHttpClient
     */
    private static HttpHelper mOkHttpHelperInstance;
    private static OkHttpClient mClientInstance;
    private Handler mHandler;
    private Gson mGson;

    private static String requestUrl;

    /**
     * 单例模式，私有构造函数，构造函数里面进行一些初始化
     */
    private HttpHelper() {
        mClientInstance = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)       //设置连接超时
                .readTimeout(60, TimeUnit.SECONDS)          //设置读超时
                .writeTimeout(60, TimeUnit.SECONDS)          //设置写超时
                .retryOnConnectionFailure(true)             //是否自动重连
                .build();
        mGson = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd HH:mm:ss")
                .create();

        mHandler = new Handler(Looper.getMainLooper());
    }

    /**
     * 获取实例
     *
     * @return
     */
    public static HttpHelper getInstance() {
        if (mOkHttpHelperInstance == null) {

            synchronized (HttpHelper.class) {
                if (mOkHttpHelperInstance == null) {
                    mOkHttpHelperInstance = new HttpHelper();
                }
            }
        }
        return mOkHttpHelperInstance;
    }

    /**
     * 封装一个request方法，不管post或者get方法中都会用到
     */
    public void request(final Request request, final HttpCallback callback) {
        requestUrl = request.url().url().toString();
        Log.e("请求URL", requestUrl);
        if (!NetWorkUtil.isNetworkAvaliable(ZhuiKeApplication.getAppContext())) {
            errorCode(ResponseCode.networkError, "");
            callbackFailure(null, callback, "网络连接不可用", ResponseCode.networkError);
            return;
        }
        //在请求之前所做的事，比如弹出对话框等
        callback.onRequestBefore();

        mClientInstance.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //errorCode(ResponseCode.msgError, "");
               // callbackFailure(null, callback, e.getMessage(), ResponseCode.msgError);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    String resString = response.body().string();
                    //返回成功回调
                    try {
                        ResponseResult result = mGson.fromJson(resString, ResponseResult.class);
                        if (result != null) {
                            if (result.getCode() == 0) {
                                //如果返回的是其他类型，则利用Gson去解析
                                JSONObject jsonObj = new JSONObject(resString);
                                Object o = null;
                                try {
                                    if(jsonObj.has("data")) {
                                        o = mGson.fromJson(jsonObj.getJSONObject("data").toString(), callback.mType);
                                    }else if(jsonObj.has("mixToc")){
                                        o = mGson.fromJson(jsonObj.getJSONObject("mixToc").toString(), callback.mType);
                                    }else if(jsonObj.has("hot")){
                                        o = mGson.fromJson(jsonObj.getJSONObject("hot").toString(), callback.mType);
                                    }else if(jsonObj.has("failed")){
                                        callbackSuccess(response, jsonObj.getString("detail"), callback);
                                    }else{
                                        o = mGson.fromJson(jsonObj.toString(), callback.mType);
                                    }
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                                callbackSuccess(response, o, callback);
                            }else {
                                callbackFailure(response, callback, result.getInfo(), result.getCode());
                            }
                        } else {
                            errorCode(ResponseCode.msgError, "");
                            if(result!=null) {
                                callbackFailure(response, callback, result.getInfo(), response.code());
                            }
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                        callbackError(response, callback, e, ResponseCode.dataError, "");
                    } catch (JsonParseException e) {
                        e.printStackTrace();
                        callbackError(response, callback, e, ResponseCode.dataError, "");
                    }
                } else {
                    //返回错误
                    //callbackFailure(response, callback, response.message(), response.code());
                }
            }

        });
    }
    public void requests(final Request request, final HttpCallback callback) {
        requestUrl = request.url().url().toString();
        Log.e("请求URL", requestUrl);
        if (!NetWorkUtil.isNetworkAvaliable(ZhuiKeApplication.getAppContext())) {
            errorCode(ResponseCode.networkError, "");
            callbackFailure(null, callback, "网络连接不可用", ResponseCode.networkError);
            return;
        }
        //在请求之前所做的事，比如弹出对话框等
        callback.onRequestBefore();

        mClientInstance.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //errorCode(ResponseCode.msgError, "");
                // callbackFailure(null, callback, e.getMessage(), ResponseCode.msgError);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    String resString = response.body().string();
                    String info = new String(resString.getBytes(), "UTF-8");
                    Log.e("response for:", requestUrl + " :" + resString);
                    callbackSuccess(response, info, callback);
                } else {
                    //返回错误
                    //callbackFailure(response, callback, response.message(), response.code());
                }
            }

        });
    }

    /**
     * 在主线程中执行的回调
     *
     * @param
     */
    private void errorCode(final int code, final String msg) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                HttpResopnseHandler.HandleError(ResponseCode.msgError, "");
            }
        });
    }

    /**
     * 在主线程中执行的回调
     *
     * @param response
     * @param
     * @param callback
     */
    private void callbackSuccess(final Response response, final Object o, final HttpCallback callback) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                callback.onSuccess(response, o);
            }
        });
    }

    /**
     * 请求出错调用
     *
     * @param response
     * @param callback
     * @param e
     */
    private void callbackError(final Response response, final HttpCallback callback, final Exception e, final int code, final String errorMsg) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                HttpResopnseHandler.HandleError(code, errorMsg);
                callback.onError(response, response.code(), e);
            }
        });
    }

    /**
     * 业务失败调用
     *
     * @param response
     * @param callback
     * @param errorMsg
     * @param code
     */
    private void callbackFailure(final Response response, final HttpCallback callback, final String errorMsg, final int code) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                HttpResopnseHandler.HandleError(code, errorMsg);
                callback.onFailure(response, errorMsg, code);
            }
        });
    }

    /**
     * 对外公开的get方法
     *
     * @param url
     * @param callback
     */
    public void get(String url, Map<String, String> params, HttpCallback callback) {
        StringBuilder tempParams = new StringBuilder();
        String requestUrl;
        if (params != null) {
            try {
                int i = 0;
                for (String key : params.keySet()) {
                    if (i == 0) {
                        tempParams.append(String.format("?%s=%s", key, URLEncoder.encode(params.get(key), "utf-8")));
                    } else {
                        tempParams.append(String.format("&%s=%s", key, URLEncoder.encode(params.get(key), "utf-8")));
                    }
                    i++;
                }
                //对参数进行URLEncoder


            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            //补全请求地址
            requestUrl = String.format("%s%s", url, tempParams.toString());
        } else {
            requestUrl = url;
        }
        //创建一个请求
        Request request = buildRequest(requestUrl, null, HttpMethodType.GET);
        request(request, callback);
    }
    /**
     * 对外公开的get方法
     *
     * @param url
     * @param callback
     */
    public void getRead(String url,String[] header, HttpCallback callback) {
        StringBuilder tempParams = new StringBuilder();
        String requestUrl;
        requestUrl = url;
        //创建一个请求
        Request request = readBuildRequest(requestUrl, header, HttpMethodType.GET);
        requests(request, callback);
    }

    private Request readBuildRequest(String url, String[] header, HttpMethodType type) {
        Request.Builder builder = new Request.Builder();
        builder.addHeader("Accept",header[0]);
        builder.addHeader("User-Agent",header[1]);
       // builder.addHeader("Accept-Encoding",header[2]);
        builder.url(url);
        if (type == HttpMethodType.GET) {
            builder.get();
        }
        return builder.build();
    }
    /**
     * 对外公开的post方法
     *
     * @param url
     * @param params
     * @param callback
     */
    public void post(String url, Map<String, Object> params, HttpCallback callback) {
        Request request = buildRequest(url, params, HttpMethodType.POST);
        request(request, callback);
    }

    /**
     * 对外公开delete方法
     *
     * @param url
     * @param params
     * @param callback
     */
    public void delete(String url, Map<String, Object> params, HttpCallback callback) {
        Request request = buildRequest(url, params, HttpMethodType.DELETE);
        request(request, callback);
    }

    /**
     * 对外公开上传资源方法无附加参数
     *
     * @param url
     * @param filePath
     * @param callback
     */
    public void uploadFile(String url, String filePath, HttpCallback callback) {
        File file = new File(filePath);
        RequestBody body = RequestBody.create(MediaType.parse("text/plain"), file);
        final Request request = new Request.Builder().url(url).post(body).build();
        request(request, callback);
    }

    /**
     * 对外公开上传资源方法 有附加参数
     *
     * @param actionUrl
     * @param paramsMap
     * @param callBack
     */
    public void uploadFile(String actionUrl, Map<String, Object> paramsMap, final HttpCallback callBack) {
        MultipartBody.Builder builder = new MultipartBody.Builder();
        //设置类型
        builder.setType(MultipartBody.FORM);
        //追加参数
        for (String key : paramsMap.keySet()) {
            Object object = paramsMap.get(key);
            if (!(object instanceof File)) {
                builder.addFormDataPart(key, object.toString());
            } else {
                File file = (File) object;
                builder.addFormDataPart(key, file.getName(), RequestBody.create(null, file));
            }
        }
        //创建RequestBody
        RequestBody body = builder.build();
        //创建Request
        final Request request = new Request.Builder().url(actionUrl).post(body).build();
        request(request, callBack);

    }

    /**
     * 对外公开上传资源方法 有附加参数
     *
     * @param actionUrl
     * @param paramsMaps
     * @param callBack
     */
    public void uploadFiles(String actionUrl, List<Map<String, Object>> list, final HttpCallback callBack) {
        MultipartBody.Builder builder = new MultipartBody.Builder();
        //设置类型
        builder.setType(MultipartBody.FORM);
        for (Map<String, Object> paramsMap : list) {
            for (String key : paramsMap.keySet()) {
                Object object = paramsMap.get(key);
                if (!(object instanceof File)) {
                    builder.addFormDataPart(key, object.toString());
                } else {
                    File file = (File) object;
                    builder.addFormDataPart(key, file.getName(), RequestBody.create(null, file));
                }
            }
        }
        //追加参数
//        for (String key : paramsMap.keySet()) {
//            Object object = paramsMap.get(key);
//            if (!(object instanceof File)) {
//                builder.addFormDataPart(key, object.toString());
//            } else {
//                File file = (File) object;
//                builder.addFormDataPart(key, file.getName(), RequestBody.create(null, file));
//            }
//        }
        //创建RequestBody
        RequestBody body = builder.build();
        //创建Request
        final Request request = new Request.Builder().url(actionUrl).post(body).build();
        request(request, callBack);

    }

    /**
     * 构建请求对象
     *
     * @param url
     * @param params
     * @param type
     * @return
     */
    private Request buildRequest(String url, Map<String, Object> params, HttpMethodType type) {
        Request.Builder builder = new Request.Builder();
        builder.addHeader("user-agent","repair-android");
        builder.url(url);
        if (type == HttpMethodType.GET) {
            builder.get();
        } else if (type == HttpMethodType.POST) {
            builder.post(buildRequestBody(params));
        } else if (type == HttpMethodType.DELETE) {
            builder.delete(buildRequestBody(params));
        }
        return builder.build();
    }

    /**
     * 通过Map的键值对构建请求对象的body
     *
     * @param params
     * @return
     */
    private RequestBody buildRequestBody(Map<String, Object> params) {
        FormBody.Builder builder = new FormBody.Builder();
        /**
         * 遍历key
         */
        if (null != params) {
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                System.out.println("Key = " + entry.getKey() + ", Value = "
                        + entry.getValue());
                builder.add(entry.getKey(), entry.getValue().toString());

            }
        }
        return builder.build();
    }

    /**
     * 这个枚举用于指明是哪一种提交方式
     */
    enum HttpMethodType {
        GET,
        POST,
        PUT,
        DELETE
    }


    public static String getRequestUrl() {
        return requestUrl;
    }

}
